package com.linyaonan.leetcode.medium._1706;

/**
 * 用一个大小为 m x n 的二维网格 grid 表示一个箱子。你有 n 颗球。箱子的顶部和底部都是开着的。
 *
 * 箱子中的每个单元格都有一个对角线挡板，跨过单元格的两个角，可以将球导向左侧或者右侧。
 *
 * 将球导向右侧的挡板跨过左上角和右下角，在网格中用 1 表示。
 * 将球导向左侧的挡板跨过右上角和左下角，在网格中用 -1 表示。
 * 在箱子每一列的顶端各放一颗球。每颗球都可能卡在箱子里或从底部掉出来。如果球恰好卡在两块挡板之间的 "V" 形图案，或者被一块挡导向到箱子的任意一侧边上，就会卡住。
 *
 * 返回一个大小为 n 的数组 answer ，其中 answer[i] 是球放在顶部的第 i 列后从底部掉出来的那一列对应的下标，如果球卡在盒子里，则返回 -1 。
 *
 * 输入：grid = [[1,1,1,-1,-1],[1,1,1,-1,-1],[-1,-1,-1,1,1],[1,1,1,1,-1],[-1,-1,-1,-1,-1]]
 * 输出：[1,-1,-1,-1,-1]
 * 解释：示例如图：
 * b0 球开始放在第 0 列上，最终从箱子底部第 1 列掉出。
 * b1 球开始放在第 1 列上，会卡在第 2、3 列和第 1 行之间的 "V" 形里。
 * b2 球开始放在第 2 列上，会卡在第 2、3 列和第 0 行之间的 "V" 形里。
 * b3 球开始放在第 3 列上，会卡在第 2、3 列和第 0 行之间的 "V" 形里。
 * b4 球开始放在第 4 列上，会卡在第 2、3 列和第 1 行之间的 "V" 形里。
 *
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode.cn/problems/where-will-the-ball-fall
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 */
class Solution {
    public int[] findBall(int[][] grid) {
        if (grid == null || grid.length == 0 || grid[0].length == 0) {
            return new int[]{};
        }

        int[] result = new int[grid[0].length];

        // 一个一个遍历
        for (int i = 0; i < grid[0].length; i++) {
            int startIndex = i;
            int ceng = 0;
            boolean isDone = false;
            while (ceng <= grid.length - 1 && !isDone) {
                int next = hasNext(grid[ceng], startIndex);
                if (next == -2) {
                    result[i] = -1;
                    isDone = true;
                } else {
                    startIndex = next;
                    ceng++;
                }
            }
            if (!isDone)
                result[i] = startIndex;
        }
        return result;
    }

    /**
     * 通过当前层的当前位置判断是否可以进入到下一层
     * @param ceng
     * @param start
     * @return
     */
    public int hasNext(int[] ceng, int start) {
        // 越界状态
        if (start < 0 || start > ceng.length - 1) {
            return -2;
        }
        // 向右移动
        if (ceng[start] == 1) {
            // 卡到边界
            if (start == ceng.length - 1) {
                return -2;
            } else {
                if (ceng[start + 1] == 1) {
                    return start + 1;
                } else {
                    return -2;
                }
            }
        } else {
            if (start == 0) {
                return -2;
            } else {
                if (ceng[start - 1] == -1) {
                    return start - 1;
                } else {
                    return -2;
                }
            }
        }
    }
}